package com.bootdo.hjh.controller;

import com.bootdo.common.service.DistConfigValueService;
import com.bootdo.common.utils.*;
import com.bootdo.hjh.cache.MemberCache;
import com.bootdo.hjh.domain.ProductDO;
import com.bootdo.hjh.domain.ProductType;
import com.bootdo.hjh.domain.UserAddress;
import com.bootdo.hjh.ex.BizException;
import com.bootdo.hjh.ex.ThrowUtils;
import com.bootdo.hjh.service.OrderService;
import com.bootdo.hjh.service.ProductService;
import com.bootdo.hjh.service.UserAddressService;
import com.bootdo.hjh.vo.ForgetPasswordVO;
import com.bootdo.hjh.vo.MemberRegVO;
import com.bootdo.system.domain.UserDO;
import com.bootdo.system.service.UserService;
import com.bootdo.system.vo.ProfileVO;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by qingyong on 2018/3/31.
 */
@Controller
public class MemberInfoController {
    private static final Logger LOGGER = LoggerFactory.getLogger(MemberInfoController.class);

    @Autowired
    ProductService productService;

    @Autowired
    UserService userService;

    @Autowired
    UserAddressService userAddressService;

    @Autowired
    MemberCache memberCache;

    @Autowired
    DistConfigValueService distConfigValueService;

    @Autowired
    OrderService orderService;

    @Autowired
    DaYuSms daYuSms;
    private static Map<String,String> syncMap = new HashMap<>();


    final static Cache<String, String> cache = CacheBuilder.newBuilder()
            //设置cache的初始大小为1000，要合理设置该值
            .initialCapacity(1000)
            //设置并发数为5，即同一时间最多只能有5个线程往cache执行写入操作
            .concurrencyLevel(5)
            //设置cache中的数据在写入之后的存活时间为10秒
            .expireAfterWrite(60, TimeUnit.SECONDS)
            //构建cache实例
            .build();

    @GetMapping("/register")
    public String registerMember(Model model){
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        Map<String,Object> recommend = Maps.newHashMap();
        Object obj = subject.getPrincipal();
        if(obj instanceof UserDO){
            recommend.put("id",((UserDO)obj).getUserId());
            recommend.put("username",((UserDO)obj).getUsername());
            recommend.put("name",((UserDO)obj).getName());
            model.addAttribute("user",recommend);
        }

        //获取商品列表
        List<ProductDO> allProducts = productService.findAllProduct();
        if (!CollectionUtils.isEmpty(allProducts)) {
            model.addAttribute("products",allProducts);
        }
        return "hjh/vipreg";
    }

    @PostMapping(value = "/member/save")
    @ResponseBody
    public R saveMember(@RequestBody MemberRegVO memberRegVO){

        R r = R.ok();
        Subject currentUser = SecurityUtils.getSubject();
        Long meUserId = ((UserDO)currentUser.getPrincipal()).getUserId();
        UserDO me = userService.get(meUserId);
        //防止页面重复提交
        String userId = syncMap.get(me.getUserId().toString());
        	ThrowUtils.throwCondition(userId!=null,101,"正在提交，请勿重复操作");
        	syncMap.put(userId, userId);
        Long invokeUserId = me.getUserId();
        try {
            if (me.getAgentLevel() == null || me.getAgentLevel() <=0) {
                return R.error(100, "只有代理及以上才能注册会员");
            }

            if (userService.saveMember(memberRegVO,invokeUserId) > 0) {

            }
        }catch (BizException e){
            r = R.error(e.getCode(),e.getMessage());
        }finally {
        		syncMap.remove(userId);
		}
        return r;
    }

    @GetMapping("/myProfile")
    public String myProfile(Model model){
    		Subject currentUser = SecurityUtils.getSubject();
            UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
    		UserDO user = userService.get(userDO.getUserId());
    		model.addAttribute("user", user);
        return "hjh/personal";
    }

    @PostMapping("/updateProfile")
    @ResponseBody
    public R updateProfile(@RequestBody ProfileVO profileVO){
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        profileVO.setUserId(userDO.getUserId());
        R r = null;
        try{
            int m = userService.updateProfile(profileVO);

            if(m>0){
                userDO.setName(profileVO.getName());
                userDO.setLiveAddress(profileVO.getLiveAddress());
                userDO.setSex(profileVO.getSex());
                userDO.setCardNumber(profileVO.getCardNumber());
                //加载缓存
                memberCache.reloadNodeFromDB(userDO.getUserId());
            }
            r = R.ok();
        }catch(BizException ex){
            r = R.error(ex.getCode(),ex.getMessage());
        }

        return r;
    }

    @PostMapping("/modify_login_pwd")
    @ResponseBody
    public R modifyLoginPwd(@RequestBody ProfileVO profileVO){
        if(StringUtils.isBlank(profileVO.getCurrLoginPwd())) {
            return R.error("登录密码不能为空");
        }
        if(StringUtils.isBlank(profileVO.getLoginPwd())) {
            return R.error("新登录密码不能为空");
        }
        if(StringUtils.isBlank(profileVO.getReLoginPwd())) {
            return R.error("确认登录密码不能为空");
        }
        if(!profileVO.getReLoginPwd().equals(profileVO.getLoginPwd())) {
            return R.error("两次密码不一致");
        }

        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        String username = userDO.getUsername();

        String oldPassword = MD5Utils.encrypt(username, profileVO.getCurrLoginPwd());
        if(!StringUtils.equals(oldPassword,userDO.getPassword())){
            return R.error(201, "当前登录密码错误");
        }

        String newPassword = MD5Utils.encrypt(username, profileVO.getLoginPwd());
        profileVO.setUserId(userDO.getUserId());
        profileVO.setLoginPwd(newPassword);
        userService.updateLoginPwd(profileVO);
        //退出
        ShiroUtils.logout();
        currentUser = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, newPassword);
        try {
            token.setRememberMe(true);
            currentUser.login(token);
            currentUser.getSession().setAttribute("user",currentUser.getPrincipal());
            return R.ok();
        } catch (AuthenticationException e) {
            return R.error("用户或密码错误");
        }
    }

    @PostMapping("/modify_pay_pwd")
    @ResponseBody
    public R modifyPayPwd(@RequestBody ProfileVO profileVO){

        if(null == profileVO.getPayPwd() || profileVO.getPayPwd().trim().equals("")) {
            return R.error("新交易密码不能为空");
        }
        if(null == profileVO.getRePayPwd() || profileVO.getRePayPwd().trim().equals("")) {
            return R.error("确认交易密码不能为空");
        }
        if(!profileVO.getRePayPwd().equals(profileVO.getPayPwd())) {
            return R.error("两次密码不一致");
        }
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        profileVO.setUserId(userDO.getUserId());
        UserDO user = userService.get(userDO.getUserId());
        if(profileVO.getCurrPayPwd() != null) {
        		String currPayPwd = MD5Utils.encrypt(profileVO.getCurrPayPwd());
        		if(!user.getPayPwd().equals(currPayPwd)) {
        			return R.error(101, "当前交易密码错误");
        		}
        }
        String newPayPwd = MD5Utils.encrypt(profileVO.getRePayPwd());
        profileVO.setPayPwd(newPayPwd);
        userService.updatePayPwd(profileVO);
        userDO.setPayPwd(newPayPwd);
        return R.ok();
    }


    @PostMapping("/modify_mobile")
    @ResponseBody
    public R modifyMobile(@RequestParam("mobile") String mobile){
        if(StringUtils.isBlank(mobile)){
            return R.error(102,"手机号不能为空");
        }
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        Long userId = userDO.getUserId();
        userService.updateMobile(mobile,userId);
        userDO.setMobile(mobile);

        //加载缓存
        memberCache.reloadNodeFromDB(userId);

        return R.ok();
    }

    @PostMapping("/modify_email")
    @ResponseBody
    public R modifyEmail(@RequestParam("email") String email){
        if(StringUtils.isBlank(email)){
            return R.error(102,"email不能为空");
        }
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        Long userId = userDO.getUserId();
        userService.updateEmail(email,userId);
        userDO.setEmail(email);
        return R.ok();
    }

    @GetMapping("/search_user")
    @ResponseBody
    public List<String> searchUser(@RequestParam("keyword") String keyword,@RequestParam(value = "findChildren",required = false) Integer findChildren){
        List<String> result = new ArrayList<>();
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        Long userId = userDO.getUserId();
        boolean flag = false;
        if(findChildren!=null && findChildren>0){
            flag = true;
        }

        return userService.searchUser(keyword,userId,flag);
    }

    @GetMapping("/address")
    public String getAddress(Model model){
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        Long userId = userDO.getUserId();

        //查询我的所有地址
        List<UserAddress> myAddress = userAddressService.getUserAddressAll(userId);
        model.addAttribute("allAddress",myAddress);
        model.addAttribute("total",myAddress!=null?myAddress.size():0);

        return "hjh/address";
    }

    /**
     * 设为默认地址
     */
    @GetMapping("/set_address_defaut")
    @ResponseBody
    public R setDefaultAddress(@RequestParam("id") Integer id){
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        Long userId = userDO.getUserId();
        UserAddress ua = new UserAddress();
        ua.setId(id);
        ua.setUserId(userId);

        userAddressService.updateAddressToDefault(ua);

        return R.ok();
    }

    /**
     * 删除地址
     */
    @GetMapping("/del_address")
    @ResponseBody
    public R delAddress(@RequestParam("id") Integer id){
        userAddressService.deleteUserAddress(id);
        return R.ok();
    }

    /**
     * 添加地址
     */
    @PostMapping("/address_save")
    @ResponseBody
    public R saveAddress(@RequestBody UserAddress userAddress){
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        Long userId = userDO.getUserId();
        userAddress.setUserId(userId);
        userAddressService.saveOrUpdateUserAddress(userAddress);
        return R.ok();
    }

    /**
     * 忘记密码
     */
    @GetMapping("/forgetPassword")
    public String forgetPasswordUrl(){
        return "hjh/forget";
    }
    @GetMapping("/forgetState")
    public String forgetState(){
        return "hjh/forget_state";
    }
    /**
     * 发送验证码
     */
    @PostMapping("/sendVerification")
    @ResponseBody
    public R sendSmsVerification(HttpServletRequest request,@RequestBody ForgetPasswordVO mobile){
        R r = null;
        try{
            String host = IPUtils.getIpAddr(request);
            LOGGER.info("发送短信的客户端IP是{}",host);
            if(cache.asMap().get(host)!=null){
                return R.error(100,"请不要频繁提交");
            }
            cache.put(host,request.getRequestedSessionId());
            userService.sendVerification(mobile.getMobile(),null);
            r = R.ok();
        }catch(BizException ex){
            r = R.error(ex.getCode(),ex.getMessage());
        }
        return r;
    }

    @PostMapping("/forgetPassword")
    @ResponseBody
    public R forgetPassword(@RequestBody ForgetPasswordVO vo){
        R r = null;
        try{
            String mobile = vo.getMobile();
            String password = vo.getPassword();
            String newPassword = vo.getNewPassword();
            String vcode = vo.getVcode();
            ThrowUtils.throwCondition(StringUtils.isBlank(mobile),100,"手机号不能为空");
            ThrowUtils.throwCondition(StringUtils.isBlank(password),101,"密码不能为空");
            ThrowUtils.throwCondition(StringUtils.isBlank(newPassword),101,"确认密码不能为空");
            ThrowUtils.throwCondition(StringUtils.isBlank(vcode),102,"验证码不能为空");
            ThrowUtils.throwCondition(!StringUtils.equals(password,newPassword),101,"确认密码不一致");
            userService.forgetPassword(mobile,vcode,password);
            r = R.ok();
        }catch (BizException ex){
            r = R.error(ex.getCode(),ex.getMessage());
        }catch (Exception ex){
            LOGGER.error("密码修改错误",ex);
            r = R.error(100,"服务器错误");
        }
        return r;

    }

    @GetMapping("/achievement")
    @ResponseBody
    public R<?> achievement(String startDate,String endDate) throws Exception{
    		List<Integer> data = userService.achievement(startDate,endDate);
    		R<?> r = R.ok();
    		r.list(data);
        return r;
    }

    @GetMapping("/achievement_date")
    @ResponseBody
    public R<?> achievementDate(String startDate,String endDate) throws Exception{
    		List<String> data = userService.achievementDate(startDate,endDate);
    		R<?> r = R.ok();
    		r.list(data);
        return r;
    }

    @GetMapping("/achievement_date_month")
    @ResponseBody
    public R<?> achievementDateMonth(String startDate,String endDate) throws Exception{
    		List<String> data = userService.achievementDateMonth(startDate,endDate);
    		R<?> r = R.ok();
    		r.list(data);
        return r;
    }

    /**
     * 补货
     */
    @GetMapping("/replenishment")
    public String replenishment(Model model,
                                @RequestParam(value = "type", defaultValue = "1", required = false) Integer type) {
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");

        Integer agentLevel = userDO.getAgentLevel();



        long price = orderService.getPrice(userDO.getUserId(), type);

        String[] two = getMin(agentLevel, type);
        int min = Integer.parseInt(two[1]);
        String memberLevel = two[0];


        // 当前用户的代理等级
        // 当前用户单价
        // 当前用户最小进货数量
        ProductType productType = ProductType.getByValue(type);
        model.addAttribute("type", type);
        model.addAttribute("typeName", productType.getName());
        model.addAttribute("memberLevel", memberLevel);
        model.addAttribute("price", price/100);
        model.addAttribute("min", min);
        return "hjh/buhuo";
    }

    private String[] getMin(Integer agentLevel, int type) {
        String[] two = new String[2];
        int min = 1;
        String memberLevel = "";
        if (agentLevel == null) {
            memberLevel = "会员";
            if (ProductType.HEI_MEI.getValue().equals(type)) {
                min = distConfigValueService.getMEMBER_BUHUO_HEI_MEI_MIN();
            }else{
                min = distConfigValueService.getMEMBER_BUHUO_MIN();
            }
        } else if (1 == agentLevel) {
            memberLevel = "代理";
            if (ProductType.HEI_MEI.getValue().equals(type)) {
                min = distConfigValueService.getPROXY_BUHUO_HEI_MEI_MIN();
            }else{
                min = distConfigValueService.getPROXY_BUHUO_MIN();
            }

        } else if (2 == agentLevel) {
            memberLevel = "初级合伙人";
            if (ProductType.HEI_MEI.getValue().equals(type)) {
                min = distConfigValueService.getJUNIOR_PARTNER_BUHUO_HEI_MEI_MIN();
            }else{
                min = distConfigValueService.getJUNIOR_PARTNER_BUHUO_MIN();
            }

        } else if (3 == agentLevel) {
            memberLevel = "中级合伙人";
            if (ProductType.HEI_MEI.getValue().equals(type)) {
                min = distConfigValueService.getINTERMEDIATE_PARTNER_BUHUO_HEI_MEI_MIN();
            }else{
                min = distConfigValueService.getINTERMEDIATE_PARTNER_BUHUO_MIN();
            }

        } else if (4 == agentLevel) {
            memberLevel = "高级合伙人";
            if (ProductType.HEI_MEI.getValue().equals(type)) {
                min = distConfigValueService.getSENIOR_PARTNER_BUHUO_HEI_MEI_MIN();
            }else{
                min = distConfigValueService.getSENIOR_PARTNER_BUHUO_MIN();
            }

        } else if (5 == agentLevel) {
            memberLevel = "联合创始人";

            if (ProductType.HEI_MEI.getValue().equals(type)) {
                min = distConfigValueService.getCOFOUNDER_BUHUO_HEI_MEI_MIN();
            }else{
                min = distConfigValueService.getCOFOUNDER_BUHUO_MIN();
            }
        }

        two[0] = memberLevel;
        two[1] = ""+min;

        return two;
    }

    @PostMapping("/replenishment")
    @ResponseBody
    public R saveReplenishment(@RequestBody Map<String, Object> data) {
        Subject subject = SecurityUtils.getSubject();
        UserDO userDO =(UserDO) subject.getPrincipal();
        Long userId = userDO.getUserId();

        // 当前用户的代理等级
        // 当前用户单价
        // 当前用户最小进货数量
        int orderId = 0;
        try {
            int amount = Integer.parseInt(data.get("amount").toString());
            int type = Integer.parseInt(data.get("type").toString());
            if (amount <= 0) {
                return R.error(1, "补货数量必须大于0");
            }
            Integer agentLevel = userDO.getAgentLevel();
            String[] two = getMin(agentLevel, type);
            int min = Integer.parseInt(two[1]);
            if (amount < min) {
                return R.error(1, "您最小补货数量为：" + min);
            }
            orderId = userService.saveReplenishment(userId, amount, type);
        }catch (BizException e) {
            if (LOGGER.isErrorEnabled()) {
                LOGGER.error("补货失败", e);
            }
            return R.error(e.getCode(), e.getMessage());
        }


        return new R(orderId);
    }

    /**
     * 升级为代理
     * @param model
     * @return
     */
    @GetMapping("upgrade")
    public String upgrade(Model model) {
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");

        Integer agentLevel = userDO.getAgentLevel();
        if (agentLevel != null && agentLevel >0) {
            model.addAttribute("exception", "您已经是代理或代理也上了，无需升级");
            model.addAttribute("url", "/");
            return "error/error";
        }

        //1:普通会员 2:金卡会员 3:vip会员

        Integer ml = userDO.getMemberLevel();
        String memberLevel = "会员";
        long price = 0;
        if (ml == null) {
            memberLevel = "心悦会员";
            price = distConfigValueService.getNEW_MEMBER_TO_PROXY_PRICE();
        } else if (1 == ml) {
            memberLevel = "普通会员";
            price = distConfigValueService.getOLD_MEMBER_TO_PROXY_PRICE();
        } else if (2 == ml) {
            memberLevel = "金卡会员";
            price = distConfigValueService.getOLD_MEMBER_TO_PROXY_PRICE();
        } else if (3 == ml) {
            memberLevel = "vip会员";
            price = distConfigValueService.getOLD_MEMBER_TO_PROXY_PRICE();
        } else {
            memberLevel = "心悦会员";
            price = distConfigValueService.getNEW_MEMBER_TO_PROXY_PRICE();
        }

        // 上级代理
        String superior = memberCache.superior(userDO.getUserId());


        model.addAttribute("memberLevel", memberLevel);
        model.addAttribute("price", price/100);
        model.addAttribute("superior", superior);
        return "hjh/upgrade";
    }

    @PostMapping("/upgrade")
    @ResponseBody
    public R saveUpgrade(@RequestBody Map<String, Object> data) {
        Subject currentUser = SecurityUtils.getSubject();
        UserDO userDO = (UserDO)currentUser.getSession().getAttribute("user");
        Long userId = userDO.getUserId();

        // 设置的上级代理
        String superior = data.get("superior").toString();

        int orderId = 0;
        try {
            orderId = userService.saveUpgrade(userId, superior);
        }catch (BizException e) {
            if (LOGGER.isErrorEnabled()) {
                LOGGER.error("升级失败", e);
            }
            return R.error(e.getCode(), e.getMessage());
        }

        return new R(orderId);
    }

}
